/******************************************************************************
 * Copyright 2007 - 2021 Realtek Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
 
#include "rtw_intf.h"
#include "wifi_mac80211_ops.h"
#include "wifi_module.h"
#include "net_device.h"
#include "rtw_wlan_config.h"
#include "harmony_types.h"
#include "harmony_service.h"
#include "hdf_wifi_cmd.h"
#include "harmony_api.h"


typedef enum {
    WLAN_BAND_2G,
    WLAN_BAND_5G,
    WLAN_BAND_BUTT
} wlan_channel_band_enum;

enum rtw_rsn_cipher {
	RTW_CIPHER_NONE,
	RTW_CIPHER_WEP40,
	RTW_CIPHER_TKIP,
	RTW_CIPHER_CCMP,
	RTW_CIPHER_WEP104,
};

/**
 * enum rtw_rsn_key_mgmt - Key management suites
 */
enum rtw_rsn_key_mgmt {
	RTW_KEY_MGMT_802_1X,
	RTW_KEY_MGMT_PSK,
	RTW_KEY_MGMT_NONE,
	RTW_KEY_MGMT_802_1X_NO_WPA,
	RTW_KEY_MGMT_WPA_NONE,
	RTW_KEY_MGMT_FT_802_1X,
	RTW_KEY_MGMT_FT_PSK,
	RTW_KEY_MGMT_802_1X_SHA256,
	RTW_KEY_MGMT_PSK_SHA256,
	RTW_KEY_MGMT_WPS,
};


enum wpa_alg {
	WPA_ALG_NONE,
	WPA_ALG_WEP,
	WPA_ALG_TKIP,
	WPA_ALG_CCMP,
	WPA_ALG_IGTK,
	WPA_ALG_PMK,
	WPA_ALG_GCMP,
	WPA_ALG_SMS4,
	WPA_ALG_KRK,
	WPA_ALG_GCMP_256,
	WPA_ALG_CCMP_256,
	WPA_ALG_BIP_GMAC_128,
	WPA_ALG_BIP_GMAC_256,
	WPA_ALG_BIP_CMAC_256
};
static int realtek_wireless_mode = WC_FLAG_MODE_INFRA; //Initially Set to INFRA Mode

int rtk_wlan_chip_init(void)
{
    int ret = 0;
	printf("%s\n",__func__);
	//Register driver
	ret = rtw_drv_entry();
	if(ret != 0) {
		printf("driver register failed,ret:%d \n",ret);
		return -1;
	}
	
	//check probe successful
	if(rtw_wifi_check_probe_ok() == 0) {
		printf("Probe Failed \n");
		rtw_drv_halt();
		return -1;
	}
    return ret;
}

int rtk_wlan_chip_deinit(void)
{    	
	printf("%s\n",__func__);
	rtw_drv_halt(); 
    return 0;
}

int rtk_driver_init(struct HdfChipDriver *chipDriver, NetDevice *netDev)
{
	printf("%s\n",__func__);
	int ret = 0;
	ret = rtw_drv_open(netDev,realtek_wireless_mode);
	if(ret != 0) {
		printf("open device failed,ret:%d \n",ret);
		return -1;
	}
    return 0;
}

int rtk_driver_deinit(struct HdfChipDriver *chipDriver, NetDevice *netDev)
{
	printf("%s\n",__func__);
	rtw_wifi_close();
    return 0;
}

int32_t rtw_setMode(NetDevice *netDev, enum WlanWorkMode mode){
	printf("%s\n",__func__);
	if(mode == WLAN_WORKMODE_STA)
    {
        rtw_wc_set_mode(netDev,WC_FLAG_MODE_INFRA);
        realtek_wireless_mode = WC_FLAG_MODE_INFRA;

    }
    else if(mode == WLAN_WORKMODE_AP)
    {
        rtw_wc_set_mode(netDev,WC_FLAG_MODE_MASTER);
        realtek_wireless_mode = WC_FLAG_MODE_MASTER;
    }
    return 0;
}

static int rtw_driver_set_key_ext(void *priv, enum wpa_alg alg,
        const u8 *addr, int key_idx,
        int set_tx, const u8 *seq,
        size_t seq_len,
        const u8 *key, size_t key_len)
{
    struct rtw_wc_encode_ext *ext = NULL;
    int ret = 0;
    int flags;

    if (seq_len > WC_ENCODE_SEQ_MAX_SIZE) {
        printf("%s: Invalid seqLen %lu \n",__func__, (unsigned long) seq_len);
        return -1;
    }

    ext = _rtw_zmalloc(sizeof(*ext) + key_len);
    if (ext == NULL)
        return -1;

    flags = key_idx + 1;
    flags |= WC_ENCODE_TEMP;

    if (alg == WPA_ALG_NONE)
        flags |= WC_ENCODE_DISABLED;

    if (addr == NULL ||_rtw_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
        ext->ext_flags |= WC_ENCODE_EXT_GROUP_KEY;
    if (set_tx)
        ext->ext_flags |= WC_ENCODE_EXT_SET_TX_KEY;

    if (addr)
        _rtw_memcpy(ext->addr,addr,ETH_ALEN);
    else
        _rtw_memset(ext->addr,0xff,ETH_ALEN);

    if (key && key_len) {
        _rtw_memcpy(ext + 1, key, key_len);
        ext->key_len = key_len;
    }

    switch (alg) {
        case WPA_ALG_NONE:
            ext->alg = WC_ENCODE_ALG_NONE;
            break;
        case WPA_ALG_WEP:
            ext->alg = WC_ENCODE_ALG_WEP;
            break;
        case WPA_ALG_TKIP:
            ext->alg = WC_ENCODE_ALG_TKIP;
            break;
        case WPA_ALG_CCMP:
            ext->alg = WC_ENCODE_ALG_CCMP;
            break;
        case WPA_ALG_PMK:
            ext->alg = WC_ENCODE_ALG_PMK;
            break;
#ifdef CONFIG_IEEE80211W
        case WPA_ALG_IGTK:
            ext->alg = WC_ENCODE_ALG_AES_CMAC;
            break;
#endif /* CONFIG_IEEE80211W */
        default:
            printf("%s: Unknown algorithm %d \n",__func__, alg);
            return -1;
    }

    if (seq && seq_len) {
        ext->ext_flags |= WC_ENCODE_EXT_RX_SEQ_VALID;
        _rtw_memcpy(ext->seq, seq, seq_len);
    }

    ret = rtw_wc_set_encodeext(priv,ext,(key_idx + 1),flags);
    if (ret < 0) {
        printf("%s: Failed to Set Encode Ext %d \n", __func__, alg);
        return ret;
    }
    _rtw_mfree(ext,sizeof(*ext) + key_len);
    return ret;
}



int32_t rtw_AddKey(struct NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr,
        struct KeyParams *params)
{
	printf("%s\n",__func__);
	int ret = 0;
    ret = rtw_wc_add_key(netDev,keyIndex,pairwise,macAddr,params);
    return ret;
}

int32_t rtw_DelKey(struct NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr)
{
	printf("%s\n",__func__);
	int ret = 0;
    ret = rtw_wc_del_key(netDev,keyIndex,pairwise,macAddr);

   	return ret;
}

int32_t rtw_SetDefaultKey(struct NetDevice *netDev, uint8_t keyIndex, bool unicast, bool multicas)
{
	printf("%s\n",__func__);
	int ret = 0;
    ret =  rtw_wc_default_key(netDev,keyIndex,unicast,multicas);
	return ret;
}

int32_t rtw_GetDeviceMacAddr(NetDevice *netDev, int32_t type, uint8_t *mac, uint8_t len)
{
	printf("%s\n",__func__);
	_rtw_memcpy(mac, netDev->macAddr, len); 
	return 0;
}
u8 is_mac_addr_zero(const u8 *mac_addr)
{
    u8 zero_mac_addr[ETH_ALEN] = {0};

    if (mac_addr == NULL) {
        return 1;
    }

    return (0 == _rtw_memcmp(zero_mac_addr, mac_addr, ETH_ALEN));
}

int32_t rtk_macaddr_check(const uint8_t *mac_addr)
{
    if ((1 == is_mac_addr_zero(mac_addr)) || ((mac_addr[0] & 0x1) == 0x1)) {
        return -1;
    }
    return 0;
}


int32_t rtw_SetMacAddr(NetDevice *netDev, uint8_t *mac, uint8_t len)
{
	printf("%s\n",__func__);
	int ret =0;
    //mac addr check
    ret = rtk_macaddr_check(mac);
    if (ret != 0) {
        return ret;
    }
    //NetifAddr update
    ret = NetIfSetMacAddr(netDev, mac, len);
    if (ret != 0) {
        return ret;
    }
    //efuse update
    ret=rtw_wc_set_addr(netDev, mac, len);
    return ret;
}

int32_t rtw_SetTxPower(NetDevice *netDev, int32_t power)
{
	printf("%s\n",__func__);
	return rtw_wc_get_txpow(netDev,power);
}

int32_t rtw_GetValidFreqsWithBand(NetDevice *netDev, int32_t band, int32_t *freqs, uint32_t *num)
{
	printf("%s\n",__func__);
	uint8_t loop;
    uint16_t n_channel;
    struct rtk_channel_info channel_list[42];
    switch (band)
    {
    case WLAN_BAND_2G:
        rtw_wc_channel_list(netDev, WLAN_BAND_2G, &n_channel, channel_list);
        break;
    case WLAN_BAND_5G:
        rtw_wc_channel_list(netDev, WLAN_BAND_5G, &n_channel, channel_list);
        break;
    default:
        return -2;
    }
    num = n_channel;
    for (loop = 0; loop < n_channel; loop++) {
        freqs[loop] = channel_list[loop].ChannelFreq;
    }
    return 0;
}
void rtkReleaseHwCapability(struct WlanHwCapability *self)
{
    uint8_t i;
    if (self == NULL) {

        return;
    }
    for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
        if (self->bands[i] != NULL) {
            _rtw_mfree(self->bands[i], 0);
            self->bands[i] = NULL;
        }
    }
    if (self->supportedRates != NULL) {
        _rtw_mfree(self->supportedRates, 0);
        self->supportedRates = NULL;
    }
    _rtw_mfree(self, 0);
}
int32_t rtw_GetHwCapability(NetDevice *netDev, struct WlanHwCapability **capability)
{
	printf("%s\n",__func__);
	uint8_t loop;
    uint16_t n_rate,n_channel;
    unsigned char sta_bssrate[13];
    struct rtk_channel_info channel_list[42];
    if (capability == NULL) {
        return -1;
    }
    struct WlanHwCapability *hwCapability = (struct WlanHwCapability *)_rtw_zmalloc(sizeof(struct WlanHwCapability));
    if (hwCapability == NULL) {
		return -1;
    }
    hwCapability->Release = rtkReleaseHwCapability;
    
    rtw_wc_channel_list(netDev, 0, &n_channel, channel_list);
    if (hwCapability->bands[IEEE80211_BAND_2GHZ] == NULL) {
        hwCapability->bands[IEEE80211_BAND_2GHZ] =
            (struct WlanBand *)_rtw_zmalloc(sizeof(struct WlanBand) + sizeof(struct WlanChannel) * n_channel);
        if (hwCapability->bands[IEEE80211_BAND_2GHZ] == NULL) {
            rtkReleaseHwCapability(hwCapability);
            return -1;
        }
    }
	
    hwCapability->htCapability = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ|
        HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ;
	
    hwCapability->bands[IEEE80211_BAND_2GHZ]->channelCount = n_channel;
    for (loop = 0; loop < n_channel; loop++) {
        hwCapability->bands[IEEE80211_BAND_2GHZ]->channels[loop].centerFreq = channel_list[loop].ChannelFreq;
        hwCapability->bands[IEEE80211_BAND_2GHZ]->channels[loop].flags =  channel_list[loop].flags;
        hwCapability->bands[IEEE80211_BAND_2GHZ]->channels[loop].channelId = channel_list[loop].ChannelNum;
    }

	rtw_wc_channel_list(netDev, 1, &n_channel, channel_list);
	if(n_channel > 0)
	{
		if (hwCapability->bands[IEEE80211_BAND_5GHZ] == NULL) {
        	hwCapability->bands[IEEE80211_BAND_5GHZ] =
            	(struct WlanBand *)_rtw_zmalloc(sizeof(struct WlanBand) + sizeof(struct WlanChannel) * n_channel);
        	if (hwCapability->bands[IEEE80211_BAND_5GHZ] == NULL) {
				rtkReleaseHwCapability(hwCapability);
            	return -1;
        	}
    	}
		hwCapability->bands[IEEE80211_BAND_5GHZ]->channelCount = n_channel;
    	for (loop = 0; loop < n_channel; loop++) {
        	hwCapability->bands[IEEE80211_BAND_5GHZ]->channels[loop].centerFreq = channel_list[loop].ChannelFreq;
        	hwCapability->bands[IEEE80211_BAND_5GHZ]->channels[loop].flags =  channel_list[loop].flags;
        	hwCapability->bands[IEEE80211_BAND_5GHZ]->channels[loop].channelId = channel_list[loop].ChannelNum;
    	}
	}
	
    rtw_wc_support_rate(netDev, &n_rate, sta_bssrate);
    hwCapability->supportedRateCount = n_rate;
    hwCapability->supportedRates = (uint16_t *)_rtw_zmalloc(sizeof(uint16_t) * n_rate);
    if (hwCapability->supportedRates == NULL) {
        rtkReleaseHwCapability(hwCapability);
        return -1;
    }
    for (loop = 0; loop < n_rate; loop++) {
        hwCapability->supportedRates[loop] = (uint16_t)sta_bssrate[loop];
    }
    *capability = hwCapability;
    return 0;
}


static int rtw_set_freq(void *priv, unsigned int channel)
{
	if (rtw_wc_set_freq(priv, WC_FLAG_SET_CHANNEL, channel) < 0) {
        return -1;
    }
    
    return 0;
    
}

static int rtw_driver_set_ssid(void *priv, const uint8_t  *ssid, int ssid_len)
{
	
    int ret = 0;
    
	if (rtw_wc_set_essid(priv,(char *)ssid,ssid_len) < 0) {
		ret = -1;
	}
    
	return ret;
    
}

static int rtw_driver_set_bssid(void *priv, const uint8_t  *bssid)
{
    
	int ret = 0;
    
	char sa_data[6];	

	if (bssid)
		_rtw_memcpy(sa_data, bssid, ETH_ALEN);
	else
		_rtw_memset(sa_data, 0, ETH_ALEN);

	if (rtw_wc_set_bssid(priv, (char *)&sa_data[0]) < 0) {
		return ret;
	}
    
	return ret;
    
}
static int rtw_driver_set_auth_param(void *drv,int idx, u32 value)
{
	int ret = 0;
	int flags;

	flags = idx & WC_AUTH_INDEX;

	if (rtw_wc_set_auth(drv, flags, value) < 0) {
		return -1;
	}
	return ret;
}
static int rtw_driver_set_drop_unencrypted(void *priv,int enabled)
{
    
    return rtw_driver_set_auth_param(priv, WC_AUTH_DROP_UNENCRYPTED,
            enabled);
}
static int rtw_driver_set_auth_alg(void *priv,uint8_t AuthType)
{
    
    //struct realtek_driver_data *drv = priv;
    int algs = 0, res;

    if (AuthType == WIFI_AUTHTYPE_OPEN_SYSTEM)
        algs |= WC_AUTH_ALG_OPEN_SYSTEM;
    if (AuthType == WIFI_AUTHTYPE_SHARED_KEY)
        algs |= WC_AUTH_ALG_SHARED_KEY;
    //if (AuthType & WPA_AUTH_ALG_LEAP)
        //algs |= WC_AUTH_ALG_LEAP;
    if (algs == 0) {
        algs = WC_AUTH_ALG_OPEN_SYSTEM;
    }

    res = rtw_driver_set_auth_param(priv, WC_AUTH_80211_AUTH_ALG,
            algs);
    //drv->auth_alg_fallback = res == -2;
    return res;
}

static int rtw_driver_set_gen_ie(void *priv, const u8 *ie,
                  size_t ie_len)
{
    struct realtek_driver_data *drv = priv;
    int ret = 0;

    ie_len = ie_len-4;
    rtw_wc_set_genie(priv, (u8 *)ie, ie_len);

    return ret;
}

static int rtw_driver_keymgmt2wext(int keymgmt)
{
    switch (keymgmt) {
        case RTW_KEY_MGMT_802_1X:
        case RTW_KEY_MGMT_802_1X_NO_WPA:
            return WC_AUTH_KEY_MGMT_802_1X;
        case RTW_KEY_MGMT_PSK:
            return WC_AUTH_KEY_MGMT_PSK;
        default:
            return 0;
    }
}

static int rtw_driver_cipher2wext(int cipher)
{
    switch (cipher) {
        case RTW_CIPHER_NONE:
            return WC_AUTH_CIPHER_NONE;
        case RTW_CIPHER_WEP40:
            return WC_AUTH_CIPHER_WEP40;
        case RTW_CIPHER_TKIP:
            return WC_AUTH_CIPHER_TKIP;
        case RTW_CIPHER_CCMP:
            return WC_AUTH_CIPHER_CCMP;
        case RTW_CIPHER_WEP104:
            return WC_AUTH_CIPHER_WEP104;
        default:
            return 0;
    }
}

static enum rtw_rsn_key_mgmt key_mgmt2driver(struct CryptoSettings crypto)
{
    if (crypto.n_akmSuites) {
        switch (crypto.akmSuites[0]) 
        {
	        case WPA_AUTH_KEY_MGMT_NONE:
		        return RTW_KEY_MGMT_NONE;
            case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
		        return RTW_KEY_MGMT_802_1X_NO_WPA;
	        case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X:
            case WPA_AUTH_KEY_MGMT_UNSPEC_802_1X:
		        return RTW_KEY_MGMT_802_1X;
            case RSN_AUTH_KEY_MGMT_FT_802_1X:
		        return RTW_KEY_MGMT_FT_802_1X;
	        case RSN_AUTH_KEY_MGMT_FT_PSK:
		        return RTW_KEY_MGMT_FT_PSK;
	        case RSN_AUTH_KEY_MGMT_802_1X_SHA256:
		        return RTW_KEY_MGMT_802_1X_SHA256;
	        case RSN_AUTH_KEY_MGMT_PSK_SHA256:
		        return RTW_KEY_MGMT_PSK_SHA256;
	        case WPA_KEY_MGMT_WPS:
		        return RTW_KEY_MGMT_WPS;
	        case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X:
            case WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X:
	        default:
		        return RTW_KEY_MGMT_PSK;
        }
	}
}

static enum rtw_rsn_cipher cipher_suite2driver(struct CryptoSettings crypto)
{
    
	if(crypto.n_ciphersPairwise){
        switch (crypto.ciphersPairwise[0]) {
	        case RSN_CIPHER_SUITE_NONE:
            case WPA_CIPHER_SUITE_NONE:
		        return RTW_CIPHER_NONE;
	        case RSN_CIPHER_SUITE_WEP40:
		        return RTW_CIPHER_WEP40;
	        case RSN_CIPHER_SUITE_WEP104:
		        return RTW_CIPHER_WEP104;
	        case RSN_CIPHER_SUITE_CCMP:
            case WPA_CIPHER_SUITE_CCMP:
		        return RTW_CIPHER_CCMP;
	        case RSN_CIPHER_SUITE_TKIP:
            case WPA_CIPHER_SUITE_TKIP:
	        default:
		        return RTW_CIPHER_TKIP;
	    }
    }

}
static enum rtw_rsn_cipher ciphergroup2driver(struct CryptoSettings crypto)
{
  if(crypto.cipherGroup)
    {
        switch (crypto.cipherGroup) {
            case RSN_CIPHER_SUITE_NONE:
            case WPA_CIPHER_SUITE_NONE:
		        return RTW_CIPHER_NONE;
	        case RSN_CIPHER_SUITE_WEP40:
		        return RTW_CIPHER_WEP40;
	        case RSN_CIPHER_SUITE_WEP104:
		        return RTW_CIPHER_WEP104;
	        case RSN_CIPHER_SUITE_CCMP:
            case WPA_CIPHER_SUITE_CCMP:
		        return RTW_CIPHER_CCMP;
	        case RSN_CIPHER_SUITE_TKIP:
            case WPA_CIPHER_SUITE_TKIP:
	        default:
		        return RTW_CIPHER_TKIP;
	    }
    }
}

static int realtek_drv_set_key(void *priv,
        enum wpa_alg alg, const u8 *addr,
        int key_idx, int set_tx,
        const u8 *seq, size_t seq_len,
        const u8 *key, size_t key_len)
{
    int ret = 0, mode = 0;

	if (realtek_wireless_mode == WC_FLAG_MODE_INFRA) {
    ret = rtw_driver_set_key_ext(priv, alg, addr, key_idx, set_tx,
            seq, seq_len, key, key_len);
    if (ret == 0)
        return 0;

   if (ret != 0 &&
   			(alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) {
        ret = 0;
    } else {
        return ret;
    }

		//mode = WC_FLAG_ENCODE_OPEN;
		if (alg == WPA_ALG_NONE)
			mode = WC_FLAG_ENCODE_DISABLED;

		if (set_tx)
			mode |= WC_FLAG_ENCODE_TXKEY;

		rtw_wc_set_wep_config(priv,(u8*)key,key_len,(key_idx + 1),mode);

		return ret;
	} else if (realtek_wireless_mode == WC_FLAG_MODE_MASTER) {

		struct rtw_ieee_param *param;	
		u8 *buf;
		char *alg_str;
		size_t blen;

		blen = (sizeof(*param)) + key_len;
		buf = _rtw_zmalloc(blen);
		if (buf == NULL)
			return -1;

		param = (struct rtw_ieee_param *)buf;
		param->cmd = RTL871X_SET_ENCRYPTION;
		if (addr == NULL)
			_rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
		else
			_rtw_memcpy(param->sta_addr, addr, ETH_ALEN);


		switch (alg) {
			case WPA_ALG_NONE:
				alg_str = "none";
				break;
			case WPA_ALG_WEP:
				//cipher = IEEE80211_CIPHER_WEP;
				alg_str = "WEP";
				break;
			case WPA_ALG_TKIP:
				//cipher = IEEE80211_CIPHER_TKIP;
				alg_str = "TKIP";
				break;
			case WPA_ALG_CCMP:
				//cipher = IEEE80211_CIPHER_AES_CCM;
				alg_str = "CCMP";
				break;
			default:
				printf("%s: unknown/unsupported algorithm %d\n",
						__func__, alg);
				return -1;
		}	

		strlcpy((char *) param->u.crypt.alg, alg_str,
				IEEE_CRYPT_ALG_NAME_LEN);

		//param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
		param->u.crypt.set_tx = set_tx ? 1 : 0;
		param->u.crypt.idx = key_idx;
		param->u.crypt.key_len = key_len;

		//memcpy((u8 *) (param + 1), key, key_len);
		_rtw_memcpy(param->u.crypt.key, key, key_len);

		ret = rtw_wc_hostapd_set_encryption(priv, param, blen);
		if (ret < 0)
		{
			printf("Failed to set encryption %d\n",ret);
			ret = -1;
		}

		_rtw_mfree(buf);
		return ret;
	}

    return ret;
}
static int rtw_driver_set_psk(struct realtek_driver_data *drv,
        const u8 *psk)
{
    return 0;
}
int32_t rtw_wifi_Connect(NetDevice *netDev, WlanConnectParams *param)
{
	printf("%s\n",__func__);
	int ret = 0;
    int allow_unencrypted_eapol = 1;
    int value;
    enum rtw_rsn_key_mgmt key_mgmt;

    if (rtw_wc_set_mode(netDev,WC_FLAG_MODE_INFRA) < 0) {
        ret = -1;
    }

    if (rtw_driver_set_drop_unencrypted(netDev,param->privacy) < 0) {
        ret = -1;
    }
    if (rtw_driver_set_auth_alg(netDev, param->authType) < 0) {
        ret = -1;
    }
    if (!param->bssid && rtw_driver_set_bssid(netDev, NULL) < 0) {
        ret = -1;
    }

    if (rtw_driver_set_gen_ie(netDev, param->ie,
                param->ieLen) < 0) {
            ret = -1;
    }


    if(param->crypto.wpaVersions == WPA_VERSION_1)
    {
        value = WC_AUTH_WPA_VERSION_WPA;
    }
    else if(param->crypto.wpaVersions == WPA_VERSION_2)
    {
        value = WC_AUTH_WPA_VERSION_WPA2;
    }
    else{
        value = WC_AUTH_WPA_VERSION_DISABLED;
    }
    if (rtw_driver_set_auth_param(netDev, WC_AUTH_WPA_VERSION,
                value) < 0) {
            ret = -1;
    }

    value = key_mgmt2driver(param->crypto);
    value = rtw_driver_keymgmt2wext(value);
    if (rtw_driver_set_auth_param(netDev, WC_AUTH_KEY_MGMT, value) < 0) {
        ret = -1;
    }

    value = cipher_suite2driver(param->crypto);
    value = rtw_driver_cipher2wext(value);
    if ((value == RTW_KEY_MGMT_NONE) ||
            (value == RTW_KEY_MGMT_802_1X_NO_WPA)) {
        u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
        realtek_drv_set_key(netDev, WPA_ALG_WEP,
                    bcast, param->keyIdx, 1, NULL, 0,
                   param->key, param->keyLen);
    }
    value = ciphergroup2driver(param->crypto);
    value = rtw_driver_cipher2wext(value);
    if (rtw_driver_set_auth_param(netDev, WC_AUTH_CIPHER_PAIRWISE,value) < 0) {
        ret = -1;
    }
    value = ciphergroup2driver(param->crypto);
    value = rtw_driver_cipher2wext(value);
    if (rtw_driver_set_auth_param(netDev, WC_AUTH_CIPHER_GROUP,value) < 0) {
        ret = -1;
    }

    key_mgmt = key_mgmt2driver(param->crypto);
    value = key_mgmt != RTW_KEY_MGMT_NONE ||key_mgmt!= RTW_CIPHER_NONE ||
            key_mgmt != RTW_CIPHER_NONE ||param->ieLen;
    if (rtw_driver_set_auth_param(netDev, WC_AUTH_PRIVACY_INVOKED,
                value) < 0) {
        ret = -1;
    }

    if ((key_mgmt == RTW_KEY_MGMT_802_1X) || (key_mgmt== RTW_KEY_MGMT_PSK)) {
        allow_unencrypted_eapol = 0;
    }
    if (rtw_driver_set_psk(netDev, param->key) < 0) {
        ret = -1;
    }  
    if (rtw_driver_set_auth_param(netDev, WC_AUTH_RX_UNENCRYPTED_EAPOL,
                allow_unencrypted_eapol) < 0) {
        ret = -1;
    }
    if (param->centerFreq && rtw_set_freq(netDev, param->centerFreq) < 0) {
        ret = -1;
    }
    if (param->ssid && rtw_driver_set_ssid(netDev, param->ssid, param->ssidLen) < 0) {
        ret = -1;
    }
    if (param->bssid && rtw_driver_set_bssid(netDev, param->bssid) < 0) {
        ret = -1;
    }
    return ret;
}
static int rtw_driver_mlme(void *priv,
        const u8 *addr, int cmd, int reason_code)
{
    int ret = 0;
    if (rtw_wc_set_mlme(priv, cmd, reason_code, (char *)addr) < 0) {
        return ret;
    }
    return ret;
}

int32_t rtw_wifi_Disconnect(NetDevice *netDev, uint16_t reasonCode)
{
	printf("%s\n",__func__);
	int ret;
    u8 *addr;
    addr = netDev->macAddr;
    ret = rtw_driver_mlme(netDev, addr, WC_MLME_DISASSOC, reasonCode);
    return ret;
}

int32_t rtw_sta_StartScan(NetDevice *netDev, struct WlanScanRequest *param)
{
    printf("%s\n",__func__);
    const u8 *ssid = param->ssids[0].ssid;
    size_t ssid_len = param->ssids[0].ssidLen;
    int32_t ret,timeout;
	struct rtw_scan_req *scan_req;
	scan_req = _rtw_malloc(sizeof(struct rtw_scan_req));
	if (scan_req == NULL)
        return -1;
	
	if (ssid && ssid_len) {
		scan_req->essid_len = ssid_len;
		_rtw_memcpy(scan_req->essid, ssid, ssid_len);
		scan_req->flags = WC_SCAN_THIS_ESSID;
	}

     ret = rtw_wc_set_scan(netDev,scan_req);

    if(scan_req!=NULL)
		_rtw_mfree(scan_req);
    return ret;
    
}

int32_t rtw_sta_AbortScan(NetDevice *netDev)
{
	printf("%s\n",__func__);
	int ret;
    ret = rtw_wc_abort_scan(netDev);
    return ret;
}

int32_t rtw_scan_by_MacAddr(NetDevice *netDev, unsigned char *mac, uint32_t len)
{
    /* not support    */
    (void)netDev;
    (void)mac;
    (void)len;
    return -2;
}

static struct HdfMac80211BaseOps g_rtkbaseOps = {
    .SetMode = rtw_setMode,
    .AddKey = rtw_AddKey,
    .DelKey = rtw_DelKey,
    .SetDefaultKey = rtw_SetDefaultKey,
    .GetDeviceMacAddr = rtw_GetDeviceMacAddr,
    .SetMacAddr = rtw_SetMacAddr,
    .SetTxPower = rtw_SetTxPower,
    .GetValidFreqsWithBand = rtw_GetValidFreqsWithBand,
    .GetHwCapability = rtw_GetHwCapability
};


static struct HdfMac80211STAOps g_rtkstaOps = {
    .Connect = rtw_wifi_Connect,
    .Disconnect = rtw_wifi_Disconnect,
    .StartScan = rtw_sta_StartScan,
    .AbortScan =rtw_sta_AbortScan,
    .SetScanningMacAddress = rtw_scan_by_MacAddr
};

int32_t rtw_ConfigAp(NetDevice *netDev, struct WlanAPConf *apConf)
{
	printf("%s\n",__func__);
	struct rtk_APConf apconf;

	_rtw_memcpy(apconf.ssid, apConf->ssidConf.ssid, apConf->ssidConf.ssidLen);
	apconf.ssidLen=apConf->ssidConf.ssidLen;
	apconf.channel=apConf->channel;
	apconf.centerFreq1=apConf->centerFreq1;
	apconf.centerFreq2=apConf->centerFreq2;
	apconf.band=apConf->band;
	apconf.width=apConf->width;
	rtw_wc_set_ap_config(netDev,&apconf);
	return 0;
}

int32_t rtw_StartAp(NetDevice *netDev)
{
	printf("%s\n",__func__);
	rtw_wc_set_ap_start(netDev);
	return 0;
}
int32_t rtw_StopAp(NetDevice *netDev){
	printf("%s\n",__func__);
	return 0;
}

int32_t rtw_ConfigBeacon(NetDevice *netDev, struct WlanBeaconConf *beaconConf)
{
	printf("%s\n",__func__);
	rtw_wc_set_ap_beacon(netDev,beaconConf);
	return 0;
}

int32_t rtw_DelStation(NetDevice *netDev, const uint8_t *macAddr){
	printf("%s\n",__func__);
	rtw_wc_set_remove_sta(netDev,macAddr);
	return 0;
}

int32_t rtw_SetCountryCode(NetDevice *netDev, const char *code, uint32_t len){
	printf("%s\n",__func__);
	int region;
	
	rtw_wc_set_region_code(netDev, code,len);
	return 0;
}
int32_t rtw_GetAssociatedStasCount(NetDevice *netDev, uint32_t *num)
{
	printf("%s\n",__func__);
	rtw_wc_ap_get_sta_num(netDev, num);
	return 0;
}

int32_t rtw_GetAssociatedStasInfo(NetDevice *netDev, WifiStaInfo *staInfo, uint32_t num){
	printf("%s\n",__func__);
	rtw_wc_ap_get_sta_list(netDev,staInfo,num);
	return 0;
}
static struct HdfMac80211APOps g_rtkapOps = {
    .ConfigAp = rtw_ConfigAp,
    .StartAp = rtw_StartAp,
    .StopAp = rtw_StopAp,
    .ConfigBeacon = rtw_ConfigBeacon,
    .DelStation = rtw_DelStation,
    .SetCountryCode = rtw_SetCountryCode,
    .GetAssociatedStasCount = rtw_GetAssociatedStasCount,
    .GetAssociatedStasInfo = rtw_GetAssociatedStasInfo
};

void rtkMac80211Init(struct HdfChipDriver *chipDriver)
{
    if (chipDriver == NULL) {  
        return;
    }
    chipDriver->ops = &g_rtkbaseOps;
    chipDriver->staOps = &g_rtkstaOps;
    chipDriver->apOps = &g_rtkapOps;
}